package com.douxg.fastCoding.db.mysql;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.StrUtil;
import com.douxg.fastCoding.db.ColumnsEO;
import com.douxg.fastCoding.db.DbFunction;
import com.douxg.fastCoding.db.DbManager;
import com.douxg.fastCoding.spring.consts.BizCode;
import com.douxg.fastCoding.spring.exception.BizRuntimeException;
import com.douxg.fastCoding.spring.util.PageUtil;
import com.douxg.fastCoding.web.entity.DbInfo;
import com.douxg.fastCoding.web.eo.DbInfoEo;
import com.jfinal.plugin.activerecord.DbPro;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description
 * @Auther douxg
 * @Date 2020/7/15 10:06
 */
@Component
@Slf4j
public class MysqlFunction implements DbFunction {

    @Override
    public List<ColumnsEO> getColumnsEo(DbInfoEo dbInfoEo, String tableName) {
        if (StrUtil.isBlank(tableName)) {
            throw new BizRuntimeException(BizCode.PARAM_ISNULL);
        }
        handleJdbcUrl(dbInfoEo);
        DbPro db = DbManager.getDb(dbInfoEo);
        List<Record> records = db.find("select * from information_schema.COLUMNS where TABLE_SCHEMA = (select database()) and TABLE_NAME='" + tableName + "'");
        List<ColumnsEO> list = new ArrayList<>();
        for (Record record : records) {
            CopyOptions copyOptions = CopyOptions.create();
            copyOptions.setIgnoreCase(true);
            Columns columns = BeanUtil.fillBeanWithMap(record.getColumns(), new Columns(), true, copyOptions);
            ColumnsEO columnsEO = fillColumnsEO(columns);
            list.add(columnsEO);
        }
        return list;
    }

    @Override
    public void handleJdbcUrl(DbInfo dbInfo) {
        String jdbcUrl = dbInfo.getJdbcUrl();
        if (jdbcUrl == null) {
            jdbcUrl = "jdbc:mysql://" + dbInfo.getHost() + ":" + dbInfo.getPort() + "/" + dbInfo.getDbName();
            dbInfo.setJdbcUrl(jdbcUrl);
        } else if (dbInfo.getHost() == null || dbInfo.getPort() == null || dbInfo.getDbName() == null) {
            String[] urlSplit = jdbcUrl.split("\\?");
            String replace = urlSplit[0].replace("jdbc:mysql://", "");
            String[] split = replace.split(":");
            try {
                dbInfo.setHost(split[0]);
                String[] split1 = split[1].split("/");
                dbInfo.setPort(split1[0]);
                dbInfo.setDbName(split1[1]);
            } catch (Exception e) {
                log.error("jdbcUrl 格式错误：" + jdbcUrl, e);
                throw new BizRuntimeException(BizCode.DB_JDBC_URL_ERROR);
            }
        }
    }

    private ColumnsEO fillColumnsEO(Columns columns) {
        ColumnsEO columnsEO = BeanUtil.copyProperties(columns, ColumnsEO.class);
        MysqlDbDataType mysqlDbDataType = MysqlDbDataType.getByName(columns.getDataType());
        columnsEO.setDbDataType(mysqlDbDataType);
        return columnsEO;
    }

    public com.baomidou.mybatisplus.extension.plugins.pagination.Page<Tables> getTables(Integer pageNum, Integer size, DbInfo dbInfo) {
        DbPro db = DbManager.getDb(BeanUtil.copyProperties(dbInfo, DbInfoEo.class));
        int current = PageUtil.handlePageIndex(pageNum);
        size = PageUtil.handlePageSize(size);
        Page<Record> paginate = db.paginate(current, size, "select *", "from information_schema.TABLES where TABLE_SCHEMA=(select database())");
        List<Tables> list = new ArrayList<>();
        for (Record record : paginate.getList()) {
            Tables tables = BeanUtil.fillBeanWithMapIgnoreCase(record.getColumns(), new Tables(), false);
            list.add(tables);
        }
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<Tables> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>();
        page.setCurrent(paginate.getPageNumber())
                .setSize(paginate.getPageSize()).setTotal(paginate.getTotalRow())
                .setPages(paginate.getTotalPage()).setRecords(list);
        return page;
    }
}
